package com.by.toolkit.utils;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

public class ByDateUtil {

    private ByDateUtil() {
    }

    public static void main(String[] args) {
        List<TimeSegment> originalSegments = new ArrayList<>();
        originalSegments.add(TimeSegment.builder()
                .startTime(1739417077L)
                .endTime(1739417340L)
                .build());
        originalSegments.add(TimeSegment.builder()
                .startTime(1739417403L)
                .endTime(1739417420L)
                .build());
        originalSegments.add(TimeSegment.builder()
                .startTime(1739417423L)
                .endTime(1739417559L)
                .build());

        int segmentLength = 300;
        List<TimeSegment> segmentedTime = segmentTime(originalSegments, segmentLength);

        for (TimeSegment segment : segmentedTime) {
            System.out.println(segment);
        }
    }

    public static List<TimeSlot> splitLocalDateTimeByMinutes(LocalDateTime start, LocalDateTime end, int minutes) {
        List<TimeSlot> timeSlots = new ArrayList<>();
        Duration duration = Duration.ofMinutes(minutes);

        LocalDateTime currentStart = start; // 保持输入时间的秒部分
        int sequenceNumber = 1; // 序号从 1 开始
        while (currentStart.isBefore(end)) {
            LocalDateTime currentEnd = currentStart.plus(duration); // 结束时间根据开始时间加上时间间隔计算
            // 如果当前段的结束时间超过了总的结束时间，则调整为总的结束时间
            if (currentEnd.isAfter(end)) {
                currentEnd = end;
            }
            timeSlots.add(new TimeSlot(sequenceNumber, currentStart, currentEnd));
            // 下一段的开始时间设置为当前段的结束时间加上 1 秒，避免重合
            currentStart = currentEnd.plusSeconds(1); // 开始时间保持秒部分
            sequenceNumber++; // 序号递增
        }

        return timeSlots;
    }

    public static List<TimeSegment> segmentTime(List<TimeSegment> originalSegments, long segmentLength) {
        originalSegments.sort(Comparator.comparingLong(TimeSegment::getStartTime));
        Queue<TimeSegment> queue = new LinkedList<>(originalSegments);
        List<TimeSegment> result = new ArrayList<>();
        if (queue.isEmpty()) {
            return result;
        }

        int idx = 1;
        long currentStart = -1;
        long currentEnd = -1;
        long remaining = segmentLength;

        while (!queue.isEmpty()) {
            TimeSegment period = queue.peek();

            if (currentStart == -1) {
                currentStart = period.getStartTime();
            }

            long duration = period.getEndTime() - period.getStartTime();

            if (duration <= remaining) {
                remaining -= duration;
                currentEnd = period.getEndTime();
                queue.poll();

                if (remaining == 0) {
                    result.add(new TimeSegment(idx++, currentStart, currentEnd));
                    currentStart = -1;
                    remaining = segmentLength;
                }
            } else {
                long end = period.getStartTime() + remaining;
                result.add(new TimeSegment(idx++, currentStart, end));
                period.setStartTime(end + 1);
                if (period.getStartTime() > period.getEndTime()) {
                    queue.poll();
                }
                currentStart = -1;
                remaining = segmentLength;
            }
        }

        if (currentStart != -1) {
            result.add(new TimeSegment(idx, currentStart, currentEnd));
        }

        return result;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TimeSlot {
        private int sequenceNumber; // 序号
        private LocalDateTime startTime;
        private LocalDateTime endTime;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TimeSegment {
        private int idx;
        private long startTime;
        private long endTime;
    }

}
